﻿// =====================================================================
// <copyright file="Validation.cs" author="David R. Guindo">
// 	Copyright (C) 2013. All rights reserved.
// </copyright>
// =====================================================================
// This code is released under the terms of the Apache 2.0 license, 
// http://apache.org/licenses/LICENSE-2.0.html
// =====================================================================

namespace AppBlock.Core.Validations
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// </summary>
    [Serializable]
    public class Validation : IValidation
    {
        /// <summary>
        ///     Entity error collection <see cref="Validation" />.
        /// </summary>
        private readonly ICollection<IValidatable> validations;

        /// <summary>
        ///     Initializes a new instance of the <see cref="Validation" /> class.
        /// </summary>
        /// <param name="validateMethod">The validate method.</param>
        public Validation(Action<IValidation> validateMethod)
        {
            ArgumentHelper.AssertIsNotNull(validateMethod, "EntityValidation", "validateMethod");
            this.validations = new Collection<IValidatable>();
            this.RaiseValidations = validateMethod;
        }

        /// <summary>
        ///     Gets a value indicating whether this instance has warnings.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance has warnings; otherwise, <c>false</c>.
        /// </value>
        public bool HasWarnings
        {
            get { return !this.Validations.OfType<IEntityValidationWarning>().Any(); }
        }

        /// <summary>
        ///     Gets or sets a value indicating whether this instance is valid.
        /// </summary>
        /// <value> <c>true</c> if this instance is valid; otherwise, <c>false</c> . </value>
        public bool IsValid
        {
            get
            {
                this.Validations.Clear();
                this.RaiseValidations.Invoke(this);
                return !this.Validations.OfType<IEntityValidationError>().Any();
            }
        }

        /// <summary>
        ///     Validations the method empty.
        /// </summary>
        /// <param name="val">The val.</param>
        public static void ValidationMethodEmpty(IValidation val)
        {
        }

        /// <summary>
        ///     Gets the validations method for raise validations.
        /// </summary>
        /// <value>
        ///     The raise validations.
        /// </value>
        public Action<IValidation> RaiseValidations { get; private set; }

        /// <summary>
        ///     Gets the errors.
        /// </summary>
        public ICollection<IValidatable> Validations
        {
            get { return this.validations; }
        }

        /// <summary>
        ///     Adds the error.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="description">The description.</param>
        public void AddError(ValidationType type, string propertyName, string description)
        {
            this.Validations.Add(new ValidationError(type, propertyName, description));
        }

        /// <summary>
        ///     Adds a warning in the entity.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="description">The description.</param>
        public void AddWarning(ValidationType type, string propertyName, string description)
        {
            this.Validations.Add(new EntityValidationWarning(type, propertyName, description));
        }

        /// <summary>
        ///     Returns a <see cref="System.String" /> that represents this instance.
        /// </summary>
        /// <returns>
        ///     A <see cref="System.String" /> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            StringBuilder stb = new StringBuilder();
            this.validations.ToList().ForEach(v => stb.AppendLine(v.ToString()));
            return stb.ToString();
        }
    }
}